/**
 *  Copyright (C) 2011  Thomas ROBIN
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package triseries;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jdom.*;
import org.jdom.input.*;

/**
 * @author tshepo
 * 
 */
public class BetaSeriesXML {

	private static final boolean DEBUG = (Main.debug || MyProperties.debug.equalsIgnoreCase("BetaSeriesXML"));
	private static String key;
	private static String user;
	private static String password; 
	private static String token = "";
	private static List<String> tvshows;

	public static void SetAutentification(String k, String u, String p) {
		if(DEBUG) System.err.println("BetaSeriesXML.SetAutentification()");
		key = k;
		user = u;
		password = p;
	}

	public static int openConnection() {
		if(DEBUG) System.err.println("BetaSeriesXML.openConnection()");
		if (!token.isEmpty()) {
			return -1;
		}
		String urlQuery = "http://api.betaseries.com/members/auth.xml?key="
				+ key + "&login=" + user + "&password=" + password;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.openConnection :\n"
				+ e.getStackTrace().toString());
			return -2;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.openConnection :\n"
				+ e.getStackTrace().toString());
			return -2;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}

		if (!valeurRetour(doc, urlQuery))
			return -3;
		token = doc.getRootElement().getChild("member").getChild("token")
				.getText();
		getMytvShows();

		return Integer
				.parseInt(doc.getRootElement().getChild("code").getText());
	}

	private static boolean valeurRetour(Document doc, String urlQuery) {
		if(DEBUG) System.err.println("BetaSeriesXML.valeurRetour("+urlQuery+")");
		
		Element root = doc.getRootElement();
		Element code = root.getChild("code");
		if (code.getText().contentEquals("1"))
			return true;
		Element errors = root.getChild("errors");
		List<?> listError = errors.getChildren("error");
		Iterator<?> i = listError.iterator();
		List<Element> error = new ArrayList<Element>();
		while (i.hasNext()) {
			error.add((Element) i.next());
		}
		erreurPrint(error, urlQuery);
		return false;
	}

	public static int closeConnection() {
		if(DEBUG) System.err.println("BetaSeriesXML.closeConnection()");
		if (token.isEmpty()) {
			return -1;
		}
		String urlQuery = "http://api.betaseries.com/members/destroy.xml?key="
				+ key + "&token=" + token;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.closeConnection :\n"
				+ e.getStackTrace().toString());
			return -2;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.closeConnection :\n"
				+ e.getStackTrace().toString());
			return -2;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		if (!valeurRetour(doc, urlQuery))
			return -3;
		token = doc.getRootElement().getChild("member").getChild("token")
				.getText();
		return Integer
				.parseInt(doc.getRootElement().getChild("code").getText());
	}

	static void addSerie(String url) {
		if(DEBUG) System.err.println("BetaSeriesXML.addSerie("+url+")");
		String urlQuery = "http://api.betaseries.com/shows/add/" + url
				+ ".xml?key=" + key + "&token=" + token;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.addSerie :\n"
				+ e.getStackTrace().toString());
			return;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.addSerie :\n"
				+ e.getStackTrace().toString());
			return;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		if (!valeurRetour(doc, urlQuery))
			return;
		tvshows.add(url);
	}

	public static boolean setDownloaded(String url, String season,
			String episode) {
		if(DEBUG) System.err.println("BetaSeriesXML.setDownloaded("+url+","+season+","+episode+")");
		String urlQuery = "http://api.betaseries.com/members/downloaded/" + url
				+ ".xml?key=" + key + "&token=" + token + "&season=" + season
				+ "&episode=" + episode;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.setDownloaded :\n"
				+ e.getStackTrace().toString());
			return false;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.setDownloaded :\n"
				+ e.getStackTrace().toString());
			return false;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		if (!valeurRetour(doc, urlQuery))
			return false;
		return doc.getRootElement().getChild("downloaded").getText()
				.contentEquals("1");
	}

	public static void setWatched(String url, String season, String episode) {
		if(DEBUG) System.err.println("BetaSeriesXML.setWatched("+url+","+season+","+episode+")");
		String urlQuery = "http://api.betaseries.com/members/watched/" + url
				+ ".xml?key=" + key + "&token=" + token + "&season=" + season
				+ "&episode=" + episode;
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.setWatched :\n"
				+ e.getStackTrace().toString());
			return;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.setWatched :\n"
				+ e.getStackTrace().toString());
			return;
		}
		valeurRetour(doc, urlQuery);

	}

	@SuppressWarnings("unchecked")
	public static boolean isNotWatched(String url, String season, String episode) {
		if(DEBUG) System.err.println("BetaSeriesXML.isNotWatched("+url+","+season+","+episode+")");
		String urlQuery = "http://api.betaseries.com/members/episodes/all.xml?key="
				+ key + "&token=" + token + "&show=" + url;
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.isNotWatched :\n"
				+ e.getStackTrace().toString());
			return false;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.isNotWatched :\n"
				+ e.getStackTrace().toString());
			return false;
		}
		if (!valeurRetour(doc, urlQuery))
			return false;
		List<Element> episodes = doc.getRootElement().getChild("episodes")
				.getChildren("episode");
		for (Element ep : episodes) {
			if (ep.getChild("url").getText().equalsIgnoreCase(url)
					&& ep.getChild("season").getText().equalsIgnoreCase(season)
					&& ep.getChild("episode").getText().equalsIgnoreCase(
							episode)) {
				return true;
			}
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	public static String getUrl(VideoFile f) {
		if(DEBUG) System.err.println("BetaSeriesXML.getUrl("+f.getShow()+f.getSeason()+"x"+f.getEpisode()+")");
		String title = f.getShow();
		String urlRetour = "";
		String[] attributes = title.split(" ");
		String urlQuery = "http://api.betaseries.com/shows/search.xml?key="
				+ key + "&title=" + title;
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processWarning("BetaSeriesXML.getUrl(" + title + ") :\n"
					+ e.getStackTrace().toString());
			return null;
		} catch (IOException e) {
			Main.processWarning("BetaSeriesXML.getUrl(" + title + ") :\n"
					+ e.getStackTrace().toString());
			return null;
		}
		int matchValue = 0;

		if (!valeurRetour(doc, urlQuery))
			return null;

		List<Element> listShow = doc.getRootElement().getChild("shows")
				.getChildren("show");
		for (Element courant : listShow) {
			int val = 0;
			for (String att : attributes) {
				Matcher m = Pattern.compile(att, Pattern.CASE_INSENSITIVE)
						.matcher(courant.getChild("title").getText());
				if (m.find()) {
					val++;
				}
			}
			if (val > matchValue
					|| (val == matchValue && courant.getChild("title")
							.getText().length() < f.getShow().length())) {
				matchValue = val;
				urlRetour = courant.getChild("url").getText();
				f.setShow(courant.getChild("title").getText());
			}
		}
		return urlRetour;
	}

	public static String getTitle(String url, VideoFile f) {
		if(DEBUG) System.err.println("BetaSeriesXML.getTitle("+url+","+f.getSeason()+"x"+f.getEpisode()+")");
		String season = f.getSeason();
		String episode = f.getEpisode();

		String urlQuery = "http://api.betaseries.com/shows/episodes.xml?key="
				+ key + "&data=" + url + "&season=" + season + "&episode="
				+ episode;
		SAXBuilder builder = new SAXBuilder();
		Document doc = null;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processWarning("BetaSeriesXML.getTitle(" + url + ","
					+ season + episode + ") :\n"
					+ e.getStackTrace().toString());
			return null;
		} catch (IOException e) {
			Main.processWarning("BetaSeriesXML.getTitle(" + url + ","
					+ season + episode + ") :\n"
					+ e.getStackTrace().toString());
			return null;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		Element code = doc.getRootElement().getChild("code");
		if (code.getText().contentEquals("1"))
			return doc.getRootElement().getChild("seasons").getChild("season")
					.getChild("episodes").getChild("episode").getChild("title")
					.getText();
	//	if (doc.getRootElement().getChild("errors").getChild("error")
	//	 .getChild("code").getText().equalsIgnoreCase("3004"))
	//	  return "";
	//	valeurRetour(doc, urlQuery);
		return "";
	}

	@SuppressWarnings("unchecked")
	public static List<BTSubtitles> getSubtitlesUrl(String url, String season,
			String episode, String langue) {
		if(DEBUG) System.err.println("BetaSeriesXML.getSubtitlesUrl("+url+","+season+","+episode+","+langue+")");
		List<BTSubtitles> btsubtitlesList = new ArrayList<BTSubtitles>();
		String urlQuery = "http://api.betaseries.com/subtitles/show/" + url
				+ ".xml?key=" + key + "&language=" + langue + "&season="
				+ season + "&episode=" + episode;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.getSubtitlesUrl(" + url
					+ "," + season + "," + episode + "," + langue + ") :\n"
				+ e.getStackTrace().toString());
			return btsubtitlesList;

		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.getSubtitlesUrl(" + url
					+ "," + season + "," + episode + "," + langue + ") :\n"
				+ e.getStackTrace().toString());
			return btsubtitlesList;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}

		if (!valeurRetour(doc, urlQuery))
			return btsubtitlesList;

		List<Element> listElements = doc.getRootElement().getChild("subtitles")
				.getChildren("subtitle");
		for (Element el : listElements) {
			btsubtitlesList.add(new BTSubtitles(el));
		}

		return btsubtitlesList;
	}

	public static List<BTSubtitles> getSubtitlesUrl(String url, String season,
			String episode) {
		return getSubtitlesUrl(url, season, episode, "VF");
	}

	@SuppressWarnings("unchecked")
	public static List<Element> getUnWatched() {
		if(DEBUG) System.err.println("BetaSeriesXML.getUnWatched()");
		List<Element> unWatched = new ArrayList<Element>();
		String urlQuery = "http://api.betaseries.com/members/episodes/all.xml?key="
				+ key + "&token=" + token;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.getUnWatched :\n"
					+ e.getStackTrace().toString());
			return unWatched;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.getUnWatched :\n"
				+ e.getStackTrace().toString());
			return unWatched;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		if (!valeurRetour(doc, urlQuery))
			return unWatched;
		if (MyProperties.setSeeNotDled) {
			return doc.getRootElement().getChild("episodes").getChildren(
					"episode");
		} else {
			List<Element> listElements = doc.getRootElement().getChild(
					"episodes").getChildren("episode");
			for (Element el : listElements) {
				if (el.getChild("downloaded").getText().contentEquals("1")) {
					unWatched.add(el);
				}
			}
		}
		return unWatched;
	}

	@SuppressWarnings("unchecked")
	private static void getMytvShows() {
		if(DEBUG) System.err.println("BetaSeriesXML.getMytvShows()");
		tvshows = new ArrayList<String>();
		String urlQuery = "http://api.betaseries.com/members/infos/" + user
				+ ".xml?key=" + key + "&token=" + token;
		SAXBuilder builder = new SAXBuilder();
		Document doc;
		try {
			doc = builder.build(urlQuery);
		} catch (JDOMException e) {
			Main.processExeption("BetaSeriesXML.getMytvShows :\n"
				+ e.getStackTrace().toString());
			return;
		} catch (IOException e) {
			Main.processExeption("BetaSeriesXML.getMytvShows :\n"
				+ e.getStackTrace().toString());
			return;
		}
		if (Main.debug || MyProperties.verbose) {
			System.out.println(urlQuery);
		}
		if (!valeurRetour(doc, urlQuery))
			return;
		List<Element> listElements = doc.getRootElement().getChild("member")
				.getChild("shows").getChildren("show");
		for (Element el : listElements) {
			tvshows.add(el.getChild("url").getText());
		}
	}

	public static boolean InShows(String showUrl) {
		if(DEBUG) System.err.println("BetaSeriesXML.InShows("+showUrl+")");
		for (String s : tvshows) {
			if (s.equals(showUrl)) {
				return true;
			}
		}
		return false;
	}

	private static void erreurPrint(List<Element> errors, String url) {
		if(DEBUG) System.err.println("BetaSeriesXML.erreurPrint("+url+")");
		String s = "api.betaseries.com - Erreurs lors de la requête suivante :\n"
				+ url;
		for (Element err : errors) {
			s += "\nErreur : " + err.getChild("code").getText() + " - "
					+ err.getChild("content").getText();
		}
		Main.processExeption(s);
	}
}
